﻿using System;
using UnityEngine;

namespace HEFramework
{
    public static class SceneTouchSystem
    {
        [EntitySystem]
        public class SceneTouchAwakeSystem : AwakeSystem<SceneTouch>
        {
            protected override void Awake(SceneTouch _self)
            {
                _self.AddChild<SpriteOutlineComponent>();
                _self.MainCamera = GameObject.Find("Main").transform.Find("MainCamera").GetComponent<Camera>();
                _self.SceneCamera = GameObject.Find("Main").transform.Find("SceneCamera").GetComponent<Camera>();
                _self.IsClick = false;
                _self.IsDrag = false;
            }
        }


        [EntitySystem]
        public class SceneTouchUpdateSystem : UpdateSystem<SceneTouch>
        {
            protected override void Update(SceneTouch _self)
            {
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
                _self.Mouse();
#else
                _self.Finger();
#endif
                _self.ShadowLookAtCamera();
            }
        }


        private static void Mouse(this SceneTouch _self)
        {
            Vector2 mousePos = Vector2.zero;
            //允许的最大移动量，超过这个值不视为点击
            float clickMaxMovement = 0.05f;
            //允许的最大按下时间，超过这个值不视为点击
            float clickMaxDuration = 0.2f;

            // 检测鼠标按下事件
            if (Input.GetMouseButtonDown(0))
            {
                _self.SelectTarget();
                mousePos = _self.MainCamera.ScreenToWorldPoint(Input.mousePosition);
                _self.ClickStartTime = Time.time;
                _self.Position = mousePos;
                _self.IsDrag = true;
            }

            // 检测鼠标松开事件
            if (Input.GetMouseButtonUp(0))
            {
                _self.ReleaseTarget();
                _self.IsDrag = false;
                float duration = Time.time - _self.ClickStartTime;
                mousePos = _self.MainCamera.ScreenToWorldPoint(Input.mousePosition);
                //判断是否为点击
                if ((mousePos - _self.Position).magnitude < clickMaxMovement && duration < clickMaxDuration)
                {
                    _self.IsClick = true;
                }
            }

            if (_self.IsClick)
            {
                _self.IsClick = false;
                _self.Click();
            }

            if (_self.IsDrag)
            {
                float duration = Time.time - _self.ClickStartTime;
                if (duration > clickMaxDuration)
                {
                    _self.Drag();
                }
            }
        }

        private static void Finger(this SceneTouch _self)
        {
        }


        private static void Click(this SceneTouch _self)
        {
        }

        private static void Drag(this SceneTouch _self)
        {
            var entity = _self.Target.Entity;
            if (entity == null)
            {
                return;
            }


            switch (_self.SelectType)
            {
                case 0:
                {
                    var ac = entity.GetChild<AttributeComponent>();
                    var tc = entity.GetChild<TransformComponent>();
                    if (ac == null || tc == null)
                    {
                        return;
                    }

                    if (_self.ShadowObject == null)
                    {
                        var pc = _self.GetSceneChild<PrefabComponent>();
                        var dc = _self.GetSceneChild<DataTableComponent>();

                        if (pc == null || dc == null)
                        {
                            return;
                        }

                        var data = dc.LoadDataTable<DRAttribute>().GetData(ac.Attribute.ID);
                        _self.ShadowObject = pc.GetPrefabSyn(data.ABPath, Formula.CN(data.ABName, 0) + "_Shadow");
                        _self.ShadowBehaviour = _self.ShadowObject.GetComponent<TransformBehaviour>();
                        _self.ShadowObject.transform.position = tc.P.ToVector();
                    }


                    Vector2 dir = _self.MainCamera.ScreenToWorldPoint(Input.mousePosition);
                    dir -= _self.Position;
                    _self.ShadowObject.transform.position = tc.P.ToVector() + (Vector3)dir * 5;
                    var soc = _self.GetChild<SpriteOutlineComponent>();
                    soc.SetTarget(_self.ShadowObject);


                    if (_self.IsReadyPlaceHero())
                    {
                        soc.SetColor(Graphics.COLOR_DEEP_GREEN);
                    }
                    else
                    {
                        soc.SetColor(Graphics.COLOR_DEEP_RED);
                    }
                }
                    break;
            }
        }


        private static void SelectTarget(this SceneTouch _self, int _type = 0)
        {
            var entity = _self.Target.Entity;
            if (entity != null)
            {
                return;
            }

            _self.SelectType = _type;

            // 将鼠标位置转换为射线
            Ray ray = _self.SceneCamera.ScreenPointToRay(Input.mousePosition);
            // 射线碰撞的信息
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.collider.CompareTag("Ground"))
                {
                    Vector3 pointOnGround = hit.point;
                    pointOnGround.z = 0;
                    using var entities = _self.GetScene().GetChildList<Entity>();
                    using var temps = ListObject<Entity>.Create();
                    for (int i = 0; i < entities.Count; i++)
                    {
                        if (!_self.IsType(entities[i], _self.SelectType))
                        {
                            continue;
                        }

                        var ac = entities[i].GetChild<AttributeComponent>();
                        var tc = entities[i].GetChild<TransformComponent>();
                        if (ac == null || tc == null)
                        {
                            continue;
                        }

                        //获取处于点击范围内的实体
                        if (Vector3.Distance(pointOnGround, tc.GetCenterPos(ac).ToVector()) < 1f)
                        {
                            temps.Add(entities[i]);
                        }
                    }


                    //选择Y值最小的，Y越小越往前
                    for (int i = 0; i < temps.Count; i++)
                    {
                        if (_self.Target.Entity == null)
                        {
                            _self.Target = temps[i];
                        }
                        else
                        {
                            var o_tc = _self.Target.Entity.GetChild<TransformComponent>();
                            if (temps[i].GetChild<TransformComponent>().P.y < o_tc.P.y)
                            {
                                _self.Target = temps[i];
                            }
                        }
                    }

                    if (_self.Target.Entity != null)
                    {
                        Log.Debug("对象" + _self.Target.Entity.GetType());
                    }
                }
            }
        }


        private static void ReleaseTarget(this SceneTouch _self)
        {
            if (_self.Target.Entity != null)
            {
                if (_self.ShadowObject != null)
                {
                    var ac = _self.Target.Entity.GetChild<AttributeComponent>();
                    if (ac != null)
                    {
                        var pc = _self.GetSceneChild<PrefabComponent>();
                        var dc = _self.GetSceneChild<DataTableComponent>();

                        if (pc == null || dc == null)
                        {
                            return;
                        }

                        switch (_self.SelectType)
                        {
                            case 0:
                                var data = dc.LoadDataTable<DRAttribute>().GetData(ac.Attribute.ID);
                                pc.Recycle(data.ABPath, Formula.CN(data.ABName, 0) + "_Shadow", _self.ShadowObject);
                                _self.IsReadyPlaceHero(true);
                                break;
                        }
                    }

                    _self.ShadowObject = null;
                }

                _self.Target = null;
            }
        }

        private static bool IsType(this SceneTouch _self, Entity _entity, int _type)
        {
            switch (_type)
            {
                case 0:
                    if (_entity is Hero)
                    {
                        return true;
                    }

                    break;
                case 1:
                    break;
                case 2:
                    break;
            }

            return false;
        }

        private static void ShadowLookAtCamera(this SceneTouch _self)
        {
            var gc = _self.GetSceneChild<GameCamera>();
            if (gc == null)
            {
                return;
            }

            if (_self.ShadowObject == null)
            {
                return;
            }

            gc.SetGameObjectRotateToCamera(_self.ShadowBehaviour.GetTransform("Transform_Body"));
        }


        private static bool IsReadyPlaceHero(this SceneTouch _self, bool _isPlace = false)
        {
            if (_self.Target.Entity == null || _self.ShadowObject == null)
            {
                return false;
            }

            var bc = _self.Target.Entity.GetChild<BlinkComponent>();
            if (bc == null)
            {
                return false;
            }


            var p = _self.ShadowObject.transform.position.ToTSVector();
            if (bc.IsCanBlink(p))
            {
                if (_isPlace)
                {
                    bc.Blink(p);
                }

                return true;
            }

            return false;
        }
    }
}